package com.yrd.bank.utils;

import javafx.beans.property.SetProperty;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanUtils {
    private static Map<Class,Map<String, PropertyDescriptor>> classPropertyDescriptors=
            new ConcurrentHashMap<>();
    public static ExpressionParser parser = new SpelExpressionParser();

    //public static String getString(Object o){
    //    try {
    //
    //    }
    //}

    public static String[] splitByFirst(String fieldName){
        return fieldName.split("\\.",2);
    }

    public static Object getFieldValue(Object o,String fieldName){
        EvaluationContext context = new StandardEvaluationContext(o);
        return parser.parseExpression(fieldName).getValue(context,Object.class);
    }

    public static void setFieldValue(Object object,String fieldName,Object fieldValue){
        if(object != null){
            if(fieldName.indexOf(".")<0){
                setProperty(object,fieldName,fieldValue);
            }else {
                String[] field = splitByFirst(fieldName);
                setFieldValue(getProperty(object,field[0]),field[1],fieldValue);
            }
        }
    }

    public static Map<String,PropertyDescriptor> getPropertyDescriptors(Class clazz){
        Map<String,PropertyDescriptor> propertyMap = classPropertyDescriptors.get(clazz);
        if(propertyMap == null){
            propertyMap = new HashMap<>();
            BeanInfo beanInfo = null;

            try {
                beanInfo = Introspector.getBeanInfo(clazz);
            } catch (IntrospectionException e) {
                e.printStackTrace();
            }

            if(beanInfo == null){
                return null;
            }


            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            PropertyDescriptor[] descriptors = propertyDescriptors;
            int vLeng = propertyDescriptors.length;

            for (int i = 0; i < vLeng; i++) {
                PropertyDescriptor propertyDescriptor = descriptors[i];
                if(propertyDescriptor.getWriteMethod() != null && propertyDescriptor.getReadMethod() != null){
                    propertyMap.put(propertyDescriptor.getName(),propertyDescriptor);
                }
            }

            classPropertyDescriptors.put(clazz,propertyMap);

        }
        return propertyMap;
    }


    public static PropertyDescriptor getPropertyDescriptor(Object object,String fieldName){
        Map<String,PropertyDescriptor> map = getPropertyDescriptors(object.getClass());
        PropertyDescriptor propertyDescriptor = map.get(fieldName);
        if(propertyDescriptor == null){
            throw new YrdException(object.getClass().getName()+"类没有"+fieldName+"属性");
        }else {
            return propertyDescriptor;
        }
    }

    public static Object getProperty(Object object,String fieldName){
        try {
            return getPropertyDescriptor(object,fieldName).getReadMethod().invoke(object);
        } catch (Exception e) {
            throw new YrdException(e);
        }
    }

    public static void setProperty(Object object,String fieldName,Object fieldValue){
        try {
            getPropertyDescriptor(object,fieldName).getWriteMethod().invoke(object,fieldValue);
        } catch (Exception e) {
            throw new YrdException(e);
        }
    }

    public static String firstUpper(String str){
        return str.substring(0,1).toUpperCase()+str.substring(1);
    }

    private static boolean containsProperty(Object object,String[] names){
        if(object instanceof List){
            return false;
        }else if(object instanceof Map){
            return false;
        }else {
            boolean ret = false;
            if(object == null){
                return ret;
            }else {
                int i=0;
                int length;
                for(length = names.length;i<length;i++){
                    try {
                        new PropertyDescriptor(names[i],object.getClass());
                    } catch (IntrospectionException e) {
                        e.printStackTrace();
                        break;
                    }
                }
                if(i == length){
                    ret = true;
                }
                return ret;
            }
        }
    }















}
